// static静态属性
class People {
  name: string;
  age: number = 0;
  address?: string;
  hobby!: string;
  static count: number

  constructor(name: string, age: number) {
    this.name = name
    this.age = age
    People.count++
  }

  doEat() {}
  doStep() {}
}
let obj = new People('张三', 18)
obj.doEat()

// 静态方法
// 例如，此时公司要分装一个时间的类
class DateUtil {
  static formatDate() {}  // 格式化日期
  static diffDateByDay() {}  // 几天前
  static diffDateByHour() {}  // 几小时前
}
DateUtil.formatDate()

// 单件模式 -- 立即创建
class Car {
  static car = new Car()
  private constructor() { console.log('创建对象') }
  doDrive() {}
}
console.log('abc')  // `类中的属性，在定义时，就会运行`，有默认值则立刻赋予。
let car1 = Car.car
let car2 = Car.car
console.log(car1 === car2)  // true

// 单件模式  -- 调用时创建
class Car2 {
  static car: Car2
  static getInstance() {
    if (!this.car) { this.car = new Car2() }
    return this.car
  }
  private constructor() { console.log('创建对象') }
  doDrive() {}
}
console.log('abc')  // `类中的属性，在定义时，就会运行`，有默认值则立刻赋予。
let car3 = Car2.getInstance()
let car4 = Car2.getInstance()
console.log(car3 === car4)  // true
// 类的get与set
class Human {
  name: string
  _age!: number
  address: string

  constructor(name: string, address: string) {
    this.name = name
    this.address = address
  }
  get age() {
    return this._age
  }
  set age(val: number) {
    if (val < 0 || val > 120) {
      throw Error('无效的年龄，请重新赋值')
    }
    this._age = val
  }
}
let obj2 = new Human('张三', '广东省')
obj2.age = 100

// 用类实现一个方法拦截器
class Man {
  name: string
  age: number
  constructor(name: string, age: number) {
    this.name = name
    this.age = age
  }
  doEat(who: string, where: string) {
    console.log(`who: ${who}, where: ${where}`)
  }
}
class StringUtil {
  static trimSpace(str: string) {
    return str.replace(/\s+/g, '')
  }
}
let dataProp = Object.getOwnPropertyDescriptor(Man.prototype, 'doEat')
let targetMethod = dataProp?.value
dataProp!.value = function(...args: any[]) {
  console.log('开始计时')
  args = args.map(item => {
    if (typeof item === 'string') {
      item = StringUtil.trimSpace(item)      
    }
    return item
  })
  targetMethod.apply(this, args)
  console.log('结束计时')
}
// dataProp?.value('王明', '酒吧')
Object.defineProperty(Man.prototype, 'doEat', dataProp!)
let man = new Man('李四', 18)
man.doEat('老 王', '酒 吧')
export { StringUtil }
